package com.ls.fw.token.service.impl;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;


/**
 * 使用Redis存储Token
 */
public class RedisTokenManager extends AbstractTokenManager {

    /**
     * Redis中Key的前缀
     */
    private static final String REDIS_KEY_PREFIX = "AUTHORIZATION_KEY_";

    /**
     * Redis中Token的前缀
     */
    private static final String REDIS_TOKEN_PREFIX = "AUTHORIZATION_TOKEN_";

    /**
     * Jedis连接池
     */
    private RedisTemplate<String, String> redis;
    
    public void setRedis(RedisTemplate<String, String> redis) {
        this.redis = redis;
        //泛型设置成Long后必须更改对应的序列化方案
        redis.setKeySerializer(new JdkSerializationRedisSerializer());
    }
    @Override
    public void delSingleRelationshipByKey(String key) {
        String token = getToken(key);
        if (token != null) {
            delete(formatKey(key), formatToken(token));
        }
    }

    @Override
    public void delRelationshipByToken(String token) {
        if (singleTokenWithUser) {
            String key = getKey(token);
            delete(formatKey(key), formatToken(token));
        }
        delete(formatToken(token));
    }

    @Override
    protected void createSingleRelationship(String key, String token) {
        String oldToken = get(formatKey(key));
        if (oldToken != null) {
            delete(formatToken(oldToken));
        }
        set(formatToken(token), key, tokenExpireSeconds);
        set(formatKey(key), token, tokenExpireSeconds);
    }

    @Override
    protected void createMultipleRelationship(String key, String token) {
        set(formatToken(token), key, tokenExpireSeconds);
    }

    @Override
    public String getKeyByToken(String token) {
        String key = get(formatToken(token));
        return key;
    }

    @Override
    protected void flushExpireAfterOperation(String key, String token) {
        if (singleTokenWithUser) {
            expire(formatKey(key), tokenExpireSeconds);
        }
        expire(formatToken(token), tokenExpireSeconds);
    }

    private String get(String key) {
    	String token = redis.boundValueOps(key).get();
    	  return token;
    }

    private void set(String key, String value, long expireSeconds) {
    	 //存储到redis并设置过期时间
        redis.boundValueOps(key).set(value, expireSeconds, TimeUnit.SECONDS);
    }

    private void expire(String key, long seconds) {
        redis.boundValueOps(key).expire(seconds, TimeUnit.SECONDS);
    }

    private void delete(String... keys) {
        redis.delete(Arrays.asList(keys));
    }

    private String getToken(String key) {
        return get(formatKey(key));
    }

    private String formatKey(String key) {
        return REDIS_KEY_PREFIX.concat(key);
    }

    private String formatToken(String token) {
        return REDIS_TOKEN_PREFIX.concat(token);
    }
    
    public String createToken(String key) {
        //使用uuid作为源token
        String token = this.formatToken(UUID.randomUUID().toString().replace("-", ""));
        //存储到redis并设置过期时间
        this.set(this.formatKey(key), token, tokenExpireSeconds );
        return token;
    }
	@Override
	public String getToken(String key, boolean createIFNoExist) {
	   String token = this.getToken(key);
	   if(createIFNoExist && StringUtils.isBlank(token) ){
		   token = this.createToken(key);
	   }
	   return token;
	}
}
